package sdk

import (
	"bytes"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"net/http"
	"strings"
	"time"
)

var httpClient = &http.Client{
	Timeout: time.Second * 60,
}

var httpHost = "http://127.0.0.1"

func SetHttpHost(host string) {
	httpHost = host
}

// 发起http请求
func httpRequest[T any](method string, url string, bodyData any, ctx *ContextValue) (T, error) {
	var resp *http.Response
	var err error
	var errRet T
	url = httpHost + "/workflow" + url
	var reader io.Reader
	if bodyData != nil {
		bts, err := json.Marshal(bodyData)
		if err != nil {
			return errRet, errors.New("参数序列化失败" + err.Error())
		}
		reader = bytes.NewReader(bts)
	}
	req, e := http.NewRequest(strings.ToUpper(method), url, reader)
	if e != nil {
		return errRet, errors.New("请求创建失败" + e.Error())
	}
	req.Header.Set("Content-Type", "application/json")
	if ctx != nil {
		req.Header.Set("UserID", ctx.UserID)
		req.Header.Set("UserName", ctx.UserName)
		req.Header.Set("OrgID", ctx.OrgID)
	}
	resp, err = httpClient.Do(req)
	if err != nil {
		return errRet, err
	}
	if resp.StatusCode != http.StatusOK {
		return errRet, fmt.Errorf("请求失败" + resp.Status)
	}
	if resp.Body == nil {
		return errRet, errors.New("请求结果空")
	}
	defer resp.Body.Close()
	result, rErr := io.ReadAll(resp.Body)
	if rErr != nil {
		return errRet, errors.New("结果读取异常" + rErr.Error())
	}
	var ret response[T]
	err = json.Unmarshal(result, &ret)
	if err != nil {
		return errRet, errors.New("结果解析异常" + err.Error())
	}
	if ret.Code != 0 {
		return errRet, errors.New(ret.Errmsg)
	}
	return ret.Data, nil
}

// FlowSave 流程保存
func FlowSave(flow Flow, ctx *ContextValue) (string, error) {
	return httpRequest[string](http.MethodPost, "/flow/create", flow, ctx)
}

// FlowQuery 查询一个流程
func FlowQuery(flowID string, ctx *ContextValue) (Flow, error) {
	return httpRequest[Flow](http.MethodGet, "/flow/query?flowID="+flowID, nil, ctx)
}

// FlowRouteQuery 流程公式查询
func FlowRouteQuery(routeID string, ctx *ContextValue) (FlowRoute, error) {
	return httpRequest[FlowRoute](http.MethodGet, "/flow/route/query?routeID="+routeID, nil, ctx)
}

// FlowQueryNodes 查询流程节点列表
func FlowQueryNodes(flowID string, ctx *ContextValue) ([]Node, error) {
	return httpRequest[[]Node](http.MethodGet, "/flow/queryNodes", nil, ctx)
}

// WorkFlowCreate 创建一个工作流
func WorkFlowCreate(flowID string, workFlowCode string, workFlowName string, ctx *ContextValue) (string, error) {
	return httpRequest[string](http.MethodPost, "/workflow/create?flowID="+flowID+"&workFlowCode="+workFlowCode+"&workFlowName="+workFlowName, nil, ctx)
}

// WorkCreate 创建一个工作
func WorkCreate(req WorkCreateReq, ctx *ContextValue) (string, error) {
	return httpRequest[string](http.MethodPost, "/work/create", req, ctx)
}

// WorkNodeDo 工作节点执行
func WorkNodeDo(workDetailID string, isPass bool, memo string, ctx *ContextValue) (string, error) {
	passString := "0"
	if isPass {
		passString = "1"
	}
	return httpRequest[string](http.MethodPost, "/work/do?workDetailID="+workDetailID+"&isPass="+passString+"&memo="+memo, nil, ctx)
}

// WorkNodes 查询所有工作节点
func WorkNodes(workID string, ctx *ContextValue) ([]WorkNode, error) {
	return httpRequest[[]WorkNode](http.MethodGet, "/work/nodes?workID="+workID, nil, ctx)
}

// EnableWorkFlow 启用工作流
func EnableWorkFlow(workFlowID string, ctx *ContextValue) error {
	_, err := httpRequest[string](http.MethodPost, "/workflow/enable?workFlowID="+workFlowID, nil, ctx)
	return err
}

// DisableWorkFlow 禁用工作流
func DisableWorkFlow(workFlowID string, ctx *ContextValue) error {
	_, err := httpRequest[string](http.MethodPost, "/workflow/disable?workFlowID="+workFlowID, nil, ctx)
	return err
}

// FlowNodeQuery 流程节点查询
func FlowNodeQuery(nodeID string) (Node, error) {
	return httpRequest[Node](http.MethodGet, "/flow/node/query?nodeID="+nodeID, nil, nil)
}

// FlowNodeUpdate 流程节点更新
func FlowNodeUpdate(req Node, ctx *ContextValue) error {
	_, err := httpRequest[string](http.MethodPost, "/flow/node/update", req, ctx)
	return err
}

// FlowDel 工作流删除
func FlowDel(flowID string, ctx *ContextValue) error {
	_, err := httpRequest[string](http.MethodDelete, "/flow/del?flowID="+flowID, nil, ctx)
	return err
}

// WaitDoWorkList 待工作列表
func WaitDoWorkList(workFlowCode string, userID string, ctx *ContextValue) ([]WorkNode, error) {
	return httpRequest[[]WorkNode](http.MethodGet, "/work/waitDo?workFlowCode="+workFlowCode+"&userID="+userID, nil, ctx)
}

// WorkFlowQuery 工作流查询,workFlowCode 工作流编码,useStatus 工作流状态(-1=全部,0=未启用,1=启用)
func WorkFlowQuery(workFlowID string, workFlowCode string, useStatus int, ctx *ContextValue) []WorkFlow {
	ret, _ := httpRequest[[]WorkFlow](http.MethodGet, "/workflow/query?workFlowCode="+workFlowCode+"&useStatus="+fmt.Sprintf("%d", useStatus)+"&workFlowID="+workFlowID, nil, ctx)
	return ret
}

// UserGroupList 用户组列表
func UserGroupList(ctx *ContextValue) ([]string, error) {
	return httpRequest[[]string](http.MethodGet, "/workflow/userGroup/list", nil, ctx)
}

// UserGroupUserIDQuery 用户组用户ID列表
func UserGroupUserIDQuery(userGroupName string, ctx *ContextValue) ([]string, error) {
	return httpRequest[[]string](http.MethodGet, "/workflow/userGroup/userIDs?userGroupName="+userGroupName, nil, ctx)
}

// UserGroupAddUserID 用户组绑定用户
func UserGroupAddUserID(userGroupName string, userID string, ctx *ContextValue) error {
	_, err := httpRequest[string](http.MethodPost, "/workflow/userGroup/userAdd?userGroupName="+userGroupName+"&userID="+userID, nil, ctx)
	return err
}

// UserGroupDelUserID 用户组移除用户
func UserGroupDelUserID(userGroupName string, userID string, ctx *ContextValue) error {
	_, err := httpRequest[string](http.MethodDelete, "/workflow/userGroup/userDel?userGroupName="+userGroupName+"&userID="+userID, nil, ctx)
	return err
}

// WorkNodeQueryByID 工作节点信息查询
func WorkNodeQueryByID(workDetailID string, ctx *ContextValue) (WorkNode, error) {
	return httpRequest[WorkNode](http.MethodGet, "/work/nodeQueryByID?workDetailID="+workDetailID, nil, ctx)
}

// WorkQueryByID 工作查询
func WorkQueryByID(workID string, ctx *ContextValue) (Work, error) {
	return httpRequest[Work](http.MethodGet, "/work/queryByID?workID="+workID, nil, ctx)
}
